package com.demo.webapp.views.freemarker.directive.core;

import java.io.IOException;
import java.io.Writer;
import java.util.Map;

import com.demo.common.StringUtils;
import com.demo.webapp.views.freemarker.directive.core.validation.exception.ParameterValidateException;

import freemarker.core.Environment;
import freemarker.core.ParseException;
import freemarker.core.Environment.TemplateDirectiveBodyEx;
import freemarker.template.SimpleHash;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;

/**
 * 自定义指令：include
 * 利用getTemplateForInclusion方法实现
 * <br>
 * 该指令提供模板引用任何文件(特别是其他模板)
 * @author ryuu.kk
 *
 */
public class IncludeDirective extends PageContextDirectiveSupport {

	/**
	 * 引用文件路径
	 */
	private String path;
	
	/**
	 * 文件编码
	 */
	private String encoding;
	
	/**
	 * 是否分解HTML
	 */
	private boolean parse;
	
	@SuppressWarnings("rawtypes")
	@Override
	public void preWriter(Environment env, TemplateDirectiveBodyEx bodyEx,
			TemplateModel[] loopVars, SimpleHash hash, Map params)
			throws IOException, TemplateException, ParameterValidateException {
		
		// 体处理
		isRender = true;
		String templateNameString = "";
		// 参数分解 
		path = getString("path", params);
		encoding = getString("encoding", params, getDefaultValue(encoding));
		parse = getBoolean("parse", params, Boolean.valueOf(getDefaultValue(encoding)));
		
		String templatePath = path;
		Template includedTemplate = null;
        try {
        	// 参数验证
        	super.validate(params);
        	// 存在安全问题:原因是templatePath可以所以指定或空,这时,不可访问的路径将可以访问,空地址将把所有模板都进行加载。
        	if (StringUtils.isNotEmpty(templatePath)) {
        		//templateNameString = TemplateCache.getFullTemplatePath(env, templatePath, templateNameString);
                includedTemplate = env.getTemplateForInclusion(templatePath, encoding, parse);
        	}
        }
        catch (ParseException pe) {
            String msg = "Error parsing included template "
                        + templateNameString  + "\n" + pe.getMessage();
            throw new TemplateException(msg, pe, env);
        }
        catch (IOException ioe) {
            String msg = "Error reading included file "
                        + templateNameString;
            throw new TemplateException(msg, ioe, env);
        }
        if (includedTemplate != null) {
        	env.include(includedTemplate);
        }
	}

	@Override
	public void afterInvoke(Writer writer) {
	}

	@SuppressWarnings("rawtypes")
	@Override
	public String getTemplatePath(Map params) {
		return "";
	}
}
